package com.easy.neo4j.service.impl.bike;

import com.easy.common.util.Result;
import com.easy.common.util.Tools;
import com.easy.neo4j.entry.Park;
import com.easy.neo4j.repository.ParkRepository;
import com.easy.neo4j.repository.PowerBikeRepository;
import com.easy.neo4j.service.RouteSchemeHandler;
import com.easy.neo4j.vo.RouteSchemeVO;
import com.easy.neo4j.entry.PowerBike;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Author: CoolPro
 * @Description: 共享单车优先
 * @Time: 2024-03-28 11:26
 **/
@Component
public class BikeFirstHandler implements RouteSchemeHandler {
    private List<RouteSchemeVO> routeSchemeVOs = new ArrayList<>();//路线方案数据
    @Resource
    private ParkRepository parkRepository;
    @Resource
    private PowerBikeRepository powersBikeRepository;
    private Integer proM = 1000;//递进公里数

    @Override
    public String getRouteScheme(String[] start, String[] end, String type) {
        //验证出发点使用共享单车的可行性
//        singleBicycleRouteScheme(start, end);
        routerParks = new HashSet<>();
        getRouteParks(start, end, type);
        return Tools.object2Json(Result.success(routerParks));
    }

    /**
     * @param parkName
     * @Author: CoolPro
     * @Date: 28/3/2024
     * @Description: 获取指定停车位的所有共享单车
     * @Name: getBikeByParkName
     * @return: java.util.List<com.eazy.eazydemo.entry.PowerBike>
     */
    public List<PowerBike> getBikeByParkName(String parkName) {
        return powersBikeRepository.findBikeByParkName(parkName);
    }

    /**
     * @param start 开始节点的经纬度信息
     * @param end   结束节点的经纬度信息
     * @Author: CoolPro
     * @Date: 28/3/2024
     * @Description: 获取两点之间的距离
     * @Name: getDistance
     * @return: java.lang.double
     */
    public Double getDistance(String[] start, String[] end) {
        double lat1 = Double.parseDouble(start[0]);
        double lon1 = Double.parseDouble(start[1]);
        double lat2 = Double.parseDouble(end[0]);
        double lon2 = Double.parseDouble(end[1]);

        // 地球半径（单位：米）
        double earthRadius = 6371000;

        // 将经纬度转换为弧度
        double phi1 = Math.toRadians(lat1);
        double phi2 = Math.toRadians(lat2);
        double deltaPhi = Math.toRadians(lat2 - lat1);
        double deltaLambda = Math.toRadians(lon2 - lon1);

        // Vincenty 公式中的参数
        double a = Math.sin(deltaPhi / 2) * Math.sin(deltaPhi / 2)
                + Math.cos(phi1) * Math.cos(phi2)
                * Math.sin(deltaLambda / 2) * Math.sin(deltaLambda / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        // 计算距离
        double distance = earthRadius * c;

        return distance;
    }


    private Set<Park> routerParks;
    private Integer limit = 500;
    private Integer behind = 100;

    public void getRouteParks(String[] start, String[] end, String type) {
        //以start为中心，搜索500米范围内的所有单车点
        List<Park> parks = parkRepository.findAllPark(start[0], start[1], String.valueOf(limit));
        //判断这些单车点距离end的距离哪个最近
        for (Park park : parks) {
            //获取距离
            List<PowerBike> bikes = powersBikeRepository.findBikeByParkName(park.getName());
            park.setCount(bikes.size());
            if(bikes.size()>0){
                long damage = bikes.stream().filter(bike -> Double.parseDouble(bike.getMileage()) > 0 && Double.parseDouble(bike.getMileage())< 5).count();
                long good = bikes.stream().filter(bike -> Double.parseDouble(bike.getMileage()) >= 5).count();
                park.setDamageCount((int) damage);
                park.setGoodCount((int) good);
            }
            double distance = getDistance(end, new String[]{park.getLat(), park.getLng()});
            park.setDistance(String.valueOf(distance));
        }
        Park res;
        Optional<Park> min = parks.stream().min(Comparator.comparingDouble(p -> Double.parseDouble(p.getDistance())));
        if (type.equals("power")) {
            Optional<Park> max = parks.stream().max(Comparator.comparingDouble(Park::getCount));
            if (max.get().getCount() == 0 && limit < 1000) {
                limit += 100;
                //如果没有符合条件的单车，就继续寻找
                if(Double.parseDouble(max.get().getDistance())<=1000){
                    res = max.get();
                }else{
                    getRouteParks(start, end, type);
                    return;
                }

            } else {
//                Double distance = getDistance(end, new String[]{min.get().getLat(), min.get().getLng()});
                if (Double.parseDouble(min.get().getDistance()) < 1000) {
                    res = min.get();
                }else{
                    res = max.get();
                }
            }
        } else {
            res = min.get();
        }
        if (routerParks.add(res)) {
            limit = 500;
        } else {
            limit += 100;
        }
        if (limit > 1000) {
            behind += 200;
        }

        if (Double.parseDouble(min.get().getDistance()) < behind) {
            return;
        }
        String[] newStart = {min.get().getLat(), min.get().getLng()};
        getRouteParks(newStart, end, type);
    }
}
